﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace CPFUI.IControl
{

    public static class KeyboardInput
    {

        /// <summary>
        /// 模拟一个按键
        /// </summary>
        public static void SendKey(Keys key)
        {
            SendKey(null, key);
        }

        /// <summary>
        /// 模拟组合键
        /// </summary>
        public static void SendKey(IEnumerable<Keys> modifierKeys, Keys key)
        {
            if (key <= 0)
            {
                return;
            }

            // 如果没有组合键，只需模拟一个按键
            if (modifierKeys == null || modifierKeys.Count() == 0)
            {
                var inputs = new NativeMethods.INPUT[1];
                inputs[0].type = NativeMethods.INPUT_KEYBOARD;
                inputs[0].inputUnion.ki.wVk = (short)key;
               UnsafeNativeMethods.SendInput(1, inputs, Marshal.SizeOf(inputs[0]));
            }

            // 需要模拟组合按键
            else
            {
                //为了模拟这种情况，输入包含切换
                //修改器键、按键和释放修改器键事件。
                //
                //例如，为了模拟Ctrl+C，我们必须发送3个输入：
                //1.按下Ctrl键。
                //2.按下C。
                //3.Ctrl被释放。
                var inputs = new NativeMethods.INPUT[modifierKeys.Count() * 2 + 1];

                int i = 0;

                // 模拟切换修改器关键帧。
                foreach (var modifierKey in modifierKeys)
                {
                    inputs[i].type = NativeMethods.INPUT_KEYBOARD;
                    inputs[i].inputUnion.ki.wVk = (short)modifierKey;
                    i++;
                }

                // 模拟按键。
                inputs[i].type = NativeMethods.INPUT_KEYBOARD;
                inputs[i].inputUnion.ki.wVk = (short)key;
                i++;

                // 模拟释放修改器关键帧。
                foreach (var modifierKey in modifierKeys)
                {
                    inputs[i].type = NativeMethods.INPUT_KEYBOARD;
                    inputs[i].inputUnion.ki.wVk = (short)modifierKey;
                    inputs[i].inputUnion.ki.dwFlags = NativeMethods.KEYEVENTF_KEYUP;
                    i++;
                }

                UnsafeNativeMethods.SendInput((uint)inputs.Length, inputs,
                    Marshal.SizeOf(inputs[0]));
            }
        }

        /// <summary>
        /// 按下可以切换的键，例如Caps Lock，
        /// Num Lock或Scroll Lock。要模拟它，应按下键，然后释放
        /// </summary>
        public static void SendToggledKey(Keys key)
        {
            var inputs = new NativeMethods.INPUT[2];

            // Press the key.
            inputs[0].type = NativeMethods.INPUT_KEYBOARD;
            inputs[0].inputUnion.ki.wVk = (short)key;
            inputs[0].inputUnion.ki.dwFlags = 0;


            // Release the key.
            inputs[1].type = NativeMethods.INPUT_KEYBOARD;
            inputs[1].inputUnion.ki.wVk = (short)key;
            inputs[1].inputUnion.ki.dwFlags = NativeMethods.KEYEVENTF_KEYUP;

            UnsafeNativeMethods.SendInput(2, inputs, Marshal.SizeOf(inputs[0]));
        }
    }
}
